/*
 * @文件描述: 按键、旋转编码器等模块
 * @版本: 
 * @作者: 周晨阳
 * @Date: 2021-01-20 13:30:03
 * @说明：
 * 普通按键采用轮询式检测
 * 旋转编码器采用外部中断的方式检测
 */
#include "myButton.h"
#ifndef WIN_SIM
#include "beeper.h"

static void (*F1_Func)();
static void (*F2_Func)();
static void (*F3_Func)();
static void (*F4_Func)();
static void (*F5_Func)();

static void (*Button1Func)();
static void (*Button2Func)();

static void (*encoder1Func)(uint8_t);
static void (*encoder2Func)(uint8_t);
static void (*encoder3Func)(uint8_t);
static void (*encoder4Func)(uint8_t);
static void (*encoder5Func)(uint8_t);
static void (*encoder6Func)(uint8_t);

static void (*encoder1ButFunc)();
static void (*encoder2ButFunc)();
static void (*encoder3ButFunc)();
static void (*encoder4ButFunc)();
static void (*encoder5ButFunc)();
static void (*encoder6ButFunc)();

static uint8_t hasButtonClicked = 0;
/**************函数定义**************/
/**
 * @description: 板载按钮回调
 * @param {type}
 * @return {type}
 */
void onButton2Clicked()
{

  printf("button1 clicked\n");
  // M_IncreaseSamplingRate();
}

/**
 * @description:板载按钮回调
 * @param {type}
 * @return {type}
 */
void onButton1Clicked()
{

  printf("button2 clicked\n");
  // M_DecreaseSamplingRate();
}

/**
 * @description: 设置板载按键1的监听函数
 * @param {type} 
 * @return {type} 
 */
void setButton1Listener(void (*callback)())
{
    Button1Func = callback;
}
/**
 * @description: 设置板载按键2的监听函数
 * @param {type} 
 * @return {type} 
 */
void setButton2Listener(void (*callback)())
{
    Button2Func = callback;
}
void setF1ButtonListener(void (*callback)())
{
    F1_Func = callback;
}
void setF2ButtonListener(void (*callback)())
{
    F2_Func = callback;
}
void setF3ButtonListener(void (*callback)())
{
    F3_Func = callback;
}
void setF4ButtonListener(void (*callback)())
{
    F4_Func = callback;
}
void setF5ButtonListener(void (*callback)())
{
    F5_Func = callback;
}
void setEncoder1Listener(void (*callback)(uint8_t))
{
    encoder1Func = callback;
}
void setEncoder2Listener(void (*callback)(uint8_t))
{
    encoder2Func = callback;
}
void setEncoder3Listener(void (*callback)(uint8_t))
{
    encoder3Func = callback;
}
void setEncoder4Listener(void (*callback)(uint8_t))
{
    encoder4Func = callback;
}
void setEncoder5Listener(void (*callback)(uint8_t))
{
    encoder5Func = callback;
}
void setEncoder6Listener(void (*callback)(uint8_t))
{
    encoder6Func = callback;
}

void setEncoder1ButListener(void (*callback)())
{
    encoder1ButFunc = callback;
}
void setEncoder2ButListener(void (*callback)())
{
    encoder2ButFunc = callback;
}
void setEncoder3ButListener(void (*callback)())
{
    encoder3ButFunc = callback;
}
void setEncoder4ButListener(void (*callback)())
{
    encoder4ButFunc = callback;
}
void setEncoder5ButListener(void (*callback)())
{
    encoder5ButFunc = callback;
}
void setEncoder6ButListener(void (*callback)())
{
    encoder6ButFunc = callback;
}
/**
 * @description: 按键扫描函数,使用了线程sleep来延时，只有按下并释放后才算一次完整的按击
 * @param {type} 
 * @return {type} 
 */
static uint8_t Key_Scan(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, uint8_t state)
{
    if (GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == state)
    {

        do
        {
            rt_thread_mdelay(10);
        } while (GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == state);

        return KEY_ON;
    }
    else
        return KEY_OFF;
}

/**
 * @description: 按键检测，加入线程，由于按键数量不多，没有采用更简洁的检测方式
 * @param {type} 
 * @return {type} 
 */
void buttonLooper()
{

    if (Button1Func != NULL)
    {
        //加入判断按键按下的语句
        if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN, 1))
        {
            (*Button1Func)();
            hasButtonClicked++;
        }
    }
    if (Button2Func != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(KEY2_GPIO_PORT, KEY2_GPIO_PIN, 1))
        {
            (*Button2Func)();
            hasButtonClicked++;
        }
    }
    if (F1_Func != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(F1_GPIO_PORT, F1_GPIO_PIN, 0))
        {
            (*F1_Func)();
            hasButtonClicked++;
        }
    }
    if (F2_Func != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(F2_GPIO_PORT, F2_GPIO_PIN, 0))
        {
            (*F2_Func)();
            hasButtonClicked++;
        }
    }
    if (F3_Func != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(F3_GPIO_PORT, F3_GPIO_PIN, 0))
        {
            (*F3_Func)();
            hasButtonClicked++;
        }
    }
    if (F4_Func != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(F4_GPIO_PORT, F4_GPIO_PIN, 0))
        {
            (*F4_Func)();
            hasButtonClicked++;
        }
    }
    if (F5_Func != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(F5_GPIO_PORT, F5_GPIO_PIN, 0))
        {
            (*F5_Func)();
            hasButtonClicked++;
        }
    }
    if (encoder1ButFunc != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(ENCODER1_BUT_GPIO_PORT, ENCODER1_BUT_GPIO_PIN, 0))
        {
            (*encoder1ButFunc)();
            hasButtonClicked++;
        }
    }
    if (encoder2ButFunc != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(ENCODER2_BUT_GPIO_PORT, ENCODER2_BUT_GPIO_PIN, 0))
        {
            (*encoder2ButFunc)();
            hasButtonClicked++;
        }
    }
    if (encoder3ButFunc != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(ENCODER3_BUT_GPIO_PORT, ENCODER3_BUT_GPIO_PIN, 0))
        {
            (*encoder3ButFunc)();
            hasButtonClicked++;
        }
    }
    if (encoder4ButFunc != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(ENCODER4_BUT_GPIO_PORT, ENCODER4_BUT_GPIO_PIN, 0))
        {
            (*encoder4ButFunc)();
            hasButtonClicked++;
        }
    }
    if (encoder5ButFunc != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(ENCODER5_BUT_GPIO_PORT, ENCODER5_BUT_GPIO_PIN, 0))
        {
            (*encoder5ButFunc)();
            hasButtonClicked++;
        }
    }
    if (encoder6ButFunc != NULL)
    {
        //加入判断按键按下的语句

        if (Key_Scan(ENCODER6_BUT_GPIO_PORT, ENCODER6_BUT_GPIO_PIN, 0))
        {
            (*encoder6ButFunc)();
            hasButtonClicked++;
        }
    }

    if (hasButtonClicked > 0)
    {
        hasButtonClicked = 0;
        beeperTrigger(BEEPER_INFO);
    }
}
/**
 * @brief : 
 * @param {uint8_t} EXTI_PortSourceGPIOx
 * @param {uint8_t} EXTI_PinSourcex
 * @param {uint32_t} EXTI_Line
 * @param {EXTITrigger_TypeDef} EXTI_Trigger
 * @param {uint8_t} NVIC_IRQChannel
 * @param {uint8_t} NVIC_IRQChannelPreemptionPriority
 * @param {uint8_t} NVIC_IRQChannelSubPriority
 * @return {*}
 */
static void EXIT_Init(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex, uint32_t EXTI_Line, EXTITrigger_TypeDef EXTI_Trigger, uint8_t NVIC_IRQChannel, uint8_t NVIC_IRQChannelPreemptionPriority, uint8_t NVIC_IRQChannelSubPriority)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    //旋转编码器外部中断初始化
    // 配置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_IRQChannelPreemptionPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_IRQChannelSubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOx, EXTI_PinSourcex);
    EXTI_InitStructure.EXTI_Line = EXTI_Line;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;

    EXTI_Init(&EXTI_InitStructure);
}

/**
 * @brief : 按键初始化集成函数，默认50M速度
 * @param {GPIO_TypeDef} *port
 * @param {uint16_t} pin
 * @param {uint32_t} clk
 * @param {GPIOPuPd_TypeDef} pupd
 * @return {*}
 * 
 */
void keyInit(GPIO_TypeDef *port, uint16_t pin, uint32_t clk, GPIOPuPd_TypeDef pupd)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(clk, ENABLE);
    GPIO_InitStructure.GPIO_Pin = pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = pupd;
    GPIO_Init(port, &GPIO_InitStructure);
}
/**
 * @brief : 旋转编码器初始化
 * @param {*}
 * @return {*}
 */
static void encoderInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能SYSCFG时钟
    keyInit(ENCODER1_A_GPIO_PORT, ENCODER1_A_GPIO_PIN, ENCODER1_A_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER1_B_GPIO_PORT, ENCODER1_B_GPIO_PIN, ENCODER1_B_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER1_BUT_GPIO_PORT, ENCODER1_BUT_GPIO_PIN, ENCODER1_BUT_GPIO_CLK, GPIO_PuPd_NOPULL);

    keyInit(ENCODER2_A_GPIO_PORT, ENCODER2_A_GPIO_PIN, ENCODER2_A_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER2_B_GPIO_PORT, ENCODER2_B_GPIO_PIN, ENCODER2_B_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER2_BUT_GPIO_PORT, ENCODER2_BUT_GPIO_PIN, ENCODER2_BUT_GPIO_CLK, GPIO_PuPd_NOPULL);

    keyInit(ENCODER3_A_GPIO_PORT, ENCODER3_A_GPIO_PIN, ENCODER3_A_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER3_B_GPIO_PORT, ENCODER3_B_GPIO_PIN, ENCODER3_B_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER3_BUT_GPIO_PORT, ENCODER3_BUT_GPIO_PIN, ENCODER3_BUT_GPIO_CLK, GPIO_PuPd_NOPULL);

    keyInit(ENCODER4_A_GPIO_PORT, ENCODER4_A_GPIO_PIN, ENCODER4_A_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER4_B_GPIO_PORT, ENCODER4_B_GPIO_PIN, ENCODER4_B_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER4_BUT_GPIO_PORT, ENCODER4_BUT_GPIO_PIN, ENCODER4_BUT_GPIO_CLK, GPIO_PuPd_NOPULL);

    keyInit(ENCODER5_A_GPIO_PORT, ENCODER5_A_GPIO_PIN, ENCODER5_A_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER5_B_GPIO_PORT, ENCODER5_B_GPIO_PIN, ENCODER5_B_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER5_BUT_GPIO_PORT, ENCODER5_BUT_GPIO_PIN, ENCODER5_BUT_GPIO_CLK, GPIO_PuPd_NOPULL);

    keyInit(ENCODER6_A_GPIO_PORT, ENCODER6_A_GPIO_PIN, ENCODER6_A_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER6_B_GPIO_PORT, ENCODER6_B_GPIO_PIN, ENCODER6_B_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(ENCODER6_BUT_GPIO_PORT, ENCODER6_BUT_GPIO_PIN, ENCODER6_BUT_GPIO_CLK, GPIO_PuPd_NOPULL);

    SYSCFG_EXTILineConfig(ENCODER1_A_EXIT_PORT, ENCODER1_A_EXIT_PIN);
    SYSCFG_EXTILineConfig(ENCODER2_A_EXIT_PORT, ENCODER2_A_EXIT_PIN);
    SYSCFG_EXTILineConfig(ENCODER3_A_EXIT_PORT, ENCODER3_A_EXIT_PIN);
    SYSCFG_EXTILineConfig(ENCODER4_A_EXIT_PORT, ENCODER4_A_EXIT_PIN);
    SYSCFG_EXTILineConfig(ENCODER5_A_EXIT_PORT, ENCODER5_A_EXIT_PIN);
    SYSCFG_EXTILineConfig(ENCODER6_A_EXIT_PORT, ENCODER6_A_EXIT_PIN);

    EXTI_InitStructure.EXTI_Line = ENCODER1_A_EXIT_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    EXTI_InitStructure.EXTI_Line = ENCODER2_A_EXIT_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    EXTI_InitStructure.EXTI_Line = ENCODER3_A_EXIT_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    EXTI_InitStructure.EXTI_Line = ENCODER4_A_EXIT_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    EXTI_InitStructure.EXTI_Line = ENCODER5_A_EXIT_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    EXTI_InitStructure.EXTI_Line = ENCODER6_A_EXIT_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
/**
 * @brief : 普通按键初始化
 * @param {*}
 * @return {*}
 */
static void buttonInit(void)
{

    keyInit(GPIOE, GPIO_Pin_4, RCC_AHB1Periph_GPIOE, GPIO_PuPd_DOWN);
    keyInit(GPIOA, GPIO_Pin_0, RCC_AHB1Periph_GPIOA, GPIO_PuPd_DOWN);

    //外部按键模块功能按键初始化
    keyInit(F1_GPIO_PORT, F1_GPIO_PIN, F1_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(F2_GPIO_PORT, F2_GPIO_PIN, F2_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(F3_GPIO_PORT, F3_GPIO_PIN, F3_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(F4_GPIO_PORT, F4_GPIO_PIN, F4_GPIO_CLK, GPIO_PuPd_NOPULL);
    keyInit(F5_GPIO_PORT, F5_GPIO_PIN, F5_GPIO_CLK, GPIO_PuPd_NOPULL);
}
/**
 * @brief : 按键模块初始化
 * @param {*}
 * @return {*}
 */
void KEY_Init(void)
{

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE, ENABLE); //使能GPIOA,GPIOE时钟

    buttonInit();
    encoderInit();
    printf("button init done...\n");
}
static void delay(uint16_t i)
{
    for (; i > 0; i--)
        ;
}

static void encoderHandler(GPIO_TypeDef *Aport, uint16_t Apin, GPIO_TypeDef *Bport, uint16_t Bpin, void (*callback)(uint8_t))
{
    if (GPIO_ReadInputDataBit(Aport, Apin))
    {
        delay(6000);
        if (GPIO_ReadInputDataBit(Aport, Apin))
        {
            if (GPIO_ReadInputDataBit(Bport, Bpin) == 1)
            {
                (*callback)(ENCODER_CW);
            }
            else
            {
                (*callback)(ENCODER_CCW);
            }
            beeperTrigger(BEEPER_INFO);
        }
    }
}
/**
 * @brief  ENCODER2_A_EXIT_LINE
 * @param  None
 * @retval None
 */
void EXTI0_IRQHandler(void)
{

    if (EXTI_GetFlagStatus(EXTI_Line0) == SET)
    {
        if (encoder2Func == NULL)
        {
            EXTI_ClearFlag(EXTI_Line0);
            return;
        }

        encoderHandler(ENCODER2_A_GPIO_PORT, ENCODER2_A_GPIO_PIN, ENCODER2_B_GPIO_PORT, ENCODER2_B_GPIO_PIN, encoder2Func);
        EXTI_ClearFlag(EXTI_Line0);
    }
}

/**
 * @brief  ENCODER1_A_EXIT_LINE
 * @param  None
 * @retval None
 */
void EXTI1_IRQHandler(void)
{

    if (EXTI_GetFlagStatus(EXTI_Line1) == SET)
    {
        if (encoder1Func == NULL)
        {
            EXTI_ClearFlag(EXTI_Line1);
            return;
        }

        encoderHandler(ENCODER1_A_GPIO_PORT, ENCODER1_A_GPIO_PIN, ENCODER1_B_GPIO_PORT, ENCODER1_B_GPIO_PIN, encoder1Func);
        EXTI_ClearFlag(EXTI_Line1);
    }
}

/**
 * @brief  ENCODER4_A_EXIT_LINE
 * @param  None
 * @retval None
 */
void EXTI2_IRQHandler(void)
{

    if (EXTI_GetFlagStatus(EXTI_Line2) == SET)
    {
        if (encoder4Func == NULL)
        {
            EXTI_ClearFlag(EXTI_Line2);
            return;
        }

        encoderHandler(ENCODER4_A_GPIO_PORT, ENCODER4_A_GPIO_PIN, ENCODER4_B_GPIO_PORT, ENCODER4_B_GPIO_PIN, encoder4Func);
        EXTI_ClearFlag(EXTI_Line2);
    }
}
/**
 * @brief  ENCODER3_A_EXIT_LINE
 * @param  None
 * @retval None
 */
void EXTI3_IRQHandler(void)
{

    if (EXTI_GetFlagStatus(EXTI_Line3) == SET)
    {
        if (encoder3Func == NULL)
        {
            EXTI_ClearFlag(EXTI_Line3);
            return;
        }
        encoderHandler(ENCODER3_A_GPIO_PORT, ENCODER3_A_GPIO_PIN, ENCODER3_B_GPIO_PORT, ENCODER3_B_GPIO_PIN, encoder3Func);
        EXTI_ClearFlag(EXTI_Line3);
    }
}

/**
 * @brief  This function handles EXTI9_5_IRQHandler interrupt request.
 * @param  None
 * @retval None
 */
void EXTI9_5_IRQHandler(void)
{

    //ENCODER5_A_EXIT_LINE
    if (EXTI_GetFlagStatus(EXTI_Line6) == SET)
    {
        if (encoder5Func == NULL)
        {
            EXTI_ClearFlag(EXTI_Line6);
            return;
        }
        encoderHandler(ENCODER5_A_GPIO_PORT, ENCODER5_A_GPIO_PIN, ENCODER5_B_GPIO_PORT, ENCODER5_B_GPIO_PIN, encoder5Func);
        EXTI_ClearFlag(EXTI_Line6);
    }

    //ENCODER6_A_EXIT_LINE
    if (EXTI_GetFlagStatus(EXTI_Line7) == SET)
    {
        if (encoder6Func == NULL)
        {
            EXTI_ClearFlag(EXTI_Line7);
            return;
        }
        encoderHandler(ENCODER6_A_GPIO_PORT, ENCODER6_A_GPIO_PIN, ENCODER6_B_GPIO_PORT, ENCODER6_B_GPIO_PIN, encoder6Func);
        EXTI_ClearFlag(EXTI_Line7);
    }
}
#endif
